﻿using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using T.FAS.Runtime.DataModel.Dao;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.FAS.Runtime.Metadata.Entity;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.DataModel.Plugin;

namespace T.FAS.Runtime.DataModel.Plugin
{
    public class EntityObjectRTPManager : AbsRTPMetaDataManager
    {       
        public const string MetaDataID = DataModelConst.EOMetaType;
        public const string MetaDataName = "实体对象";
        private readonly EntityObjectLogic _entityObjectLogic = new EntityObjectLogic();
        private readonly EntityObjectManager _entityObjectManager = new EntityObjectManager();

        public override IMetaDataContent GetMetaDataContent(string metaDataId)
        {
            if (string.IsNullOrEmpty(metaDataId))
                throw new FasException(DataModelErrorCode.NullValue, "元数据id为空");
            var eo = _entityObjectLogic.GetEntityObjectByID(metaDataId);
            if (eo == null)
                throw new FasException(DataModelErrorCode.ParamError, $"未找到{MetaDataName}:{metaDataId}的元数据");
            eo.MetaDataID   = eo.ID;
            eo.MetaDataCode = eo.Code;
            eo.MetaDataName = eo.Name;
            //等待震哥更新RTPClient方法后，将数据组装部分放到Deserialize中，减少缓存Json大小以及缓存的旧数据
            //PackagingDependencyMetaData(eo);
            return eo;
        }

        public override string SerializeObject(IMetaDataContent metadata, MetadataSerializeType serializeType)
        {
            if (serializeType == MetadataSerializeType.JSON)
            {
                //(metadata as EntityObject).ClearRef();
                return JsonConvert.SerializeObject(metadata, new JsonSerializerSettings
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                });
            }
            else
            {
                throw new NotImplementedException();
            }
        }

        public override IMetaDataContent DeserializeObject(string metaDataString, MetadataSerializeType serializeType)
        {
            if (serializeType == MetadataSerializeType.JSON)
            {
                return DeserializeObject(metaDataString, true);
            }
            else
            {
                throw new NotImplementedException();
            }
        }

        public override IMetaDataContent DeserializeObject(string metaDataString, bool isPackingData = false)
        {
            if (string.IsNullOrEmpty(metaDataString))
                throw new FasException(DataModelErrorCode.Error, $"EO反序列化Json不能为空，请检查！");
            var cdo = JsonConvert.DeserializeObject<EntityObject>(metaDataString, new JsonSerializerSettings
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            });

            if (isPackingData)
                PackagingDependencyMetaData(cdo);

            return cdo;
        }

        public override void Import(List<IMetaDataContent> contents)
        {
            _entityObjectManager.Import(contents);
        }

        public override void Delete(List<string> IDs)
        {
            _entityObjectManager.Delete(IDs);
        }

        #region Private Funcs

        private void PackagingDependencyMetaData(IMetaDataContent metaData)
        {
            InitializeMetaData(metaData as EntityObject);
        }

        private void InitializeMetaData(EntityObject entityObject, HashSet<string> EOIdCache = null, int depth = 0)
        {
            if (entityObject == null)
                return;
            if (EOIdCache == null)
                EOIdCache = new HashSet<string>();

            if (entityObject.EntityObjectAttributes != null && entityObject.EntityObjectAttributes.Count > 0)
            {
                foreach (var attr in entityObject.EntityObjectAttributes)
                {
                    if (!string.IsNullOrEmpty(attr.RelatedEntityObjectID))
                    {
                        if (attr.RelatedEntityObjectID == entityObject.ID)
                        {
                            attr.SubEntity = entityObject.Clone() as EntityObject;
                            continue;
                        }

                        //避免环路，cacheKey为EO.ID与外键EO属性 算作一条路径
                        var cacheKey = entityObject.ID + attr.Code;
                        if (!EOIdCache.Contains(cacheKey))
                        {
                            EOIdCache.Add(cacheKey);
                            attr.SubEntity = GetMetaDataWithNoDeserialize<EntityObject>(attr.RelatedEntityObjectID);
                            InitializeMetaData(attr.SubEntity, EOIdCache, depth + 1);
                        }
                    }
                }
            }
        }

        public override IRefSchemaEntity BuildRefSchema(IMetaDataContent metaDataContent)
        {
            if (metaDataContent is EntityObject eo)
            {
                return eo.BuildRefSchema();
            }
            else
            {
                throw new ArgumentNullException(nameof(metaDataContent));
            }
        }

        public override IEnumerable<Metadata.Entity.Term> BuildTerms(IMetaDataContent metaDataContent, IEnumerable<Metadata.Entity.Term> termList = null)
        {
            return default;
        }

        public override IRefSchemaEntity DeserializeRefSchemaEntity(string schemaEntityJson)
        {
            return JsonConvert.DeserializeObject<EntityObjectRefSchemaEntity>(schemaEntityJson);
        }
        #endregion

    }
}
